[转][Android][Recovery]Recovery打开adb shell


Android recovery 模式下出于安全的考虑,一般禁止adb和adb shell 登陆。如果需要在recovery 模式下进行debug,需要做一些配置修改。

烧录user版本系统,进入recovery后,输入adb shell命令,提示

error: no devices/emulators found

我们先确认recovery.img是否包含有adb (adb的源码在/system/core/adb)

ls out/target/product/bullhead/recovery/root/sbin
adbd      healthd   recovery  ueventd   watchdogd

然后检查/bootable/recovery/etc/init.rc下和adbd相关的启动配置

service adbd /sbin/adbd --root_seclabel=u:r:su:s0 --device_banner=recovery
    disabled
    socket adbd stream 660 system system
    seclabel u:r:adbd:s0

# Always start adbd on userdebug and eng builds
on property:ro.debuggable=1
    write /sys/class/android_usb/android0/enable 1
    start adbd

# Restart adbd so it can run as root
on property:service.adb.root=1
    write /sys/class/android_usb/android0/enable 0
    restart adbd
    write /sys/class/android_usb/android0/enable 1

从上面可知init.rc 中adbd 是配置的,disabled 表示开机不启动,如 ro.debuggable 被置为1,那么adb 就会开启,或是service.adb.root设置为1,则重启adbd。

看下

mvim build/core/main.mk

ifeq (true,$(strip $(enable_target_debugging)))
  # Target is more debuggable and adbd is on by default
  ADDITIONAL_DEFAULT_PROPERTIES += ro.debuggable=1
  # Enable Dalvik lock contention logging.
  ADDITIONAL_BUILD_PROPERTIES += dalvik.vm.lockprof.threshold=500
  # Include the debugging/testing OTA keys in this build.
  INCLUDE_TEST_OTA_KEYS := true
else # !enable_target_debugging
  # Target is less debuggable and adbd is off by default
  ADDITIONAL_DEFAULT_PROPERTIES += ro.debuggable=0
endif # !enable_target_debugging

关于enable_target_debugging

## user/userdebug ##

user_variant := $(filter user userdebug,$(TARGET_BUILD_VARIANT))
enable_target_debugging := true
tags_to_install :=
ifneq (,$(user_variant))
  # Target is secure in user builds.
  ADDITIONAL_DEFAULT_PROPERTIES += ro.secure=1
  ADDITIONAL_DEFAULT_PROPERTIES += security.perf_harden=1

  ifeq ($(user_variant),user)
    ADDITIONAL_DEFAULT_PROPERTIES += ro.adb.secure=1
  endif

  ifeq ($(user_variant),userdebug)
    # Pick up some extra useful tools
    tags_to_install += debug
  else
    # Disable debugging in plain user builds.
    enable_target_debugging :=
  endif

  # Disallow mock locations by default for user builds
  ADDITIONAL_DEFAULT_PROPERTIES += ro.allow.mock.location=0

else # !user_variant
  # Turn on checkjni for non-user builds.
  ADDITIONAL_BUILD_PROPERTIES += ro.kernel.android.checkjni=1
  # Set device insecure for non-user builds.
  ADDITIONAL_DEFAULT_PROPERTIES += ro.secure=0
  # Allow mock locations by default for non user builds
  ADDITIONAL_DEFAULT_PROPERTIES += ro.allow.mock.location=1
endif # !user_variant

可知默认为enable_target_debugging := true,根据user_variant的值如果为user,则enable_target_debugging :=,这又和TARGET_BUILD_VARIANT有关,此变量对应于VARIANT_CHOICES=(user userdebug eng)中的一个值,由我们来选择,相关的实现在/build/envsetup.sh中。

根据上面可知,编译时如果选择userdebug或是eng,则ro.debuggable=1,如果我们要在user下也开启这些功能,就需要修改设置

enable_target_debugging := true
ro.debuggable=0

重新编译recovery.img,刷机后,进入recovery,输入adb shell命令,提示:

Exec ‘/system/bin/sh’ failed:No such fileor directory(2)

表示没有sh这个文件,无法进入shell,检查ramdisk 文件系统 system 目录out/target/product/bullhead/recovery/root/system为空。(其实这个system是用来挂载Android的/system的,关于挂载后面会讲)

但我们知道boot.img下是可以的,看system/core/rootdir/init.rc检查boot.img 启动的init.rc。查找关于/sh的代码

service console /system/bin/sh
    class core
    console
    disabled
    user shell
    group shell log
    seclabel u:r:shell:s0

on property:ro.debuggable=1
    # Give writes to anyone for the trace folder on debug builds.
    # The folder is used to store method traces.
    chmod 0773 /data/misc/trace
    start console

所以依葫芦画瓢,我们在Recovery的/bootable/recovery/etc/init.rc添加上面的代码。

好了,虽然这一步会在Recovery启动时启动sh,但是Recovery里面没有这个文件啊(前面说了/system是个空目录,用来挂载系统的)。所以需要编译时创建这个文件,因此在/build/core/Makefile增加创建目录的代码和把系统sh拷贝到Recovery的对应目录下

define build-recoveryimage-target
    @echo ----- Making recovery image ------
    $(hide) mkdir -p $(TARGET_RECOVERY_OUT)
    $(hide) mkdir -p $(TARGET_RECOVERY_ROOT_OUT)/etc $(TARGET_RECOVERY_ROOT_OUT)/sdcard $(TARGET_RECOVERY_ROOT_OUT)/tmp
    ...
    # 添加下面代码
    $(hide) mkdir -p $(TARGET_RECOVERY_ROOT_OUT)/system/bin
    $(hide) cp -r $(PRODUCT_OUT)/system/bin/sh $(TARGET_RECOVERY_ROOT_OUT)/system/bin/

这里有个问题,就是clean掉项目重新编译的时候,系统的sh还没有生成,所以这里的拷贝操作会因为找不到sh文件而出错,需要调整代码位置。

但这样还是不行,在recovery模式下,二进制文件都是静态连接方式,recovery模式中没有共享库,缺动态链接库加载器(/system/bin/linker,Android动态连接器linker与静态连接器ld)

检查sh 连接的动态库:

arm-linux-androideabi-objdump -x out/target/product/xxxx/system/bin/sh | grep NEEDED

NEEDED libc.so

知道需要改libc的编译。

所以需要修改/external/mksh/Android.mk

#LOCAL_SYSTEM_SHARED_LIBRARIES := libc
LOCAL_STATIC_LIBRARIES := libc
LOCAL_FORCE_STATIC_EXECUTABLE := true

再次编译recovery.img,刷机,进入Recovery模式后就可以使用adb shell了。

关于没有ls命令,这些命令不可用的原理和sh一样,可以自己试着去改。

Reference

https://blog.csdn.net/LoongEmbedded/article/details/67638687


文章作者: Wossoneri
版权声明: 本博客所有文章除特別声明外,均采用 CC BY-NC 4.0 许可协议。转载请注明来源 Wossoneri !
评论
  目录